package cn.com.captureNetPacket.voice;

import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.jnetpcap.protocol.voip.Sdp;
import org.jnetpcap.protocol.voip.Sip;
import org.jnetpcap.protocol.voip.Sip.Fields;
import org.jnetpcap.protocol.voip.Sip.Method;
import org.jnetpcap.protocol.voip.Sip.Request;
import org.jnetpcap.protocol.voip.Sip.Response;

import cn.com.captureNetPacket.Analysis;
import cn.com.captureNetPacket.CaptureNetPacketService;
import cn.com.captureNetPacket.dependThirdParty.DependThirdPartyService;
import cn.com.captureNetPacket.model.NetworkInfo;
import cn.com.captureNetPacket.model.SignallingInfo;
import cn.com.captureNetPacket.model.SipPacketInfo;
import cn.com.captureNetPacket.util.RedisConfig;
import cn.com.captureNetPacket.util.Tools;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Data
@Slf4j
public class AnalysisSIP   extends Analysis{
	
	private Sip beginSip,ringingSip,establishSip,byeSip;
	private boolean beginSipAnalysis=false,ringingSipAnalysis=false,establishSipAnalysis=false,byeSipAnalysis=false;
	DependThirdPartyService dependThirdPartyService;
	
	public static  ConcurrentHashMap<String ,AnalysisSIP> analysisSIPs=new ConcurrentHashMap<String,AnalysisSIP>();
//	private    List<Sip> sips=new ArrayList<Sip>();
//	private    List<Sip> reverseSips=new ArrayList<Sip>();
	private ConcurrentLinkedQueue<SipPacketInfo> sipPacketInfos=new   ConcurrentLinkedQueue<SipPacketInfo>();
	private Sip currentSip,lastSip;private Sdp currentSdp;
	public static void addSip(NetworkInfo netInfo, Sip sip,Sdp sdp){
		 
		AnalysisSIP analysisSIP= getAnalysisSIP(netInfo);
		if(analysisSIP==null){
			synchronized (analysisSIPs) {

				//没有就初始化，开启线程去检测
				analysisSIP = new AnalysisSIP(netInfo);

				analysisSIP.setPriority(NORM_PRIORITY - 2);
				analysisSIP.setName("AnalysisSIP-Main"+netInfo.getNetworkInfoKey());
				if(getAnalysisSIP(netInfo)==null) {
					analysisSIPs.put(netInfo.getNetworkInfoKey(), analysisSIP);
					//这里放到线程池后线程sleep后无法被唤醒(interrupt失效)，在线程池中sleep后的状态一直为new，原因未知。只能先start后休眠和唤醒。 VoiceInfoPush没有这个问题，后期再查该问题
					analysisSIP.start();
//			CaptureNetPacketService.getTaskService().execute(analysisSIP);
					log.debug("flow addSip create new sip 开启了新的线程 {} ",analysisSIP.getPositiveNetworkInfo().getNetworkInfoKey());
				}else {
					analysisSIP = getAnalysisSIP(netInfo);
					log.debug("flow addSip sip 无需开启新的线程 {} ",analysisSIP.getPositiveNetworkInfo().getNetworkInfoKey());
				}
			}
		}
		SipPacketInfo sipPacketInfo=new SipPacketInfo(netInfo,sip,sdp);

//		String mediaString=sip.getAVP(Sdp.Fields.Media.toString());
//		 String connectionInfoString=sip.getAVP(Sdp.Fields.ConnectionInfo.toString());
//		 String ownerString=sip.getAVP(Sdp.Fields.Owner.toString());
		analysisSIP.getSipPacketInfos().add(sipPacketInfo);
		analysisSIP.setLastGetPacketDateTime(sipPacketInfo.getReciveTime());
//		log.debug(" addSip sip 已添加了。 {}----------->>>>>{}",analysisSIP.sipPacketInfos.size(),Tools.getjsonString(netInfo));
		//线程打断休眠开始分析
//		log.debug("--------------->>>sip:{}  analysisSIP.interrupted() {} analysisSIP.getState()：{}",netInfo.getNetworkInfoKey(),analysisSIP.isInterrupted(),analysisSIP.getState());
//		if(analysisSIP.getState()==Thread.State.TIMED_WAITING || analysisSIP.getState()==Thread.State.WAITING && !analysisSIP.isInterrupted())
//		analysisSIP.interrupt();
		analysisSIP.awaken();
//		log.debug("--------------->>>sip end:{} analysisSIP.interrupted() {}  analysisSIP.getState() :{}",netInfo.getNetworkInfoKey(),analysisSIP.isInterrupted(),analysisSIP.getState());
        
//       log.debug("addRtp sourceIP:{} port{} mac:{}->destinationIP:{}  port{}  mac:{} timestamp{}",netInfo.getSourceIP(), netInfo.getSourcePort() , netInfo.getSourceMac(),netInfo.getDestinationIP(), netInfo.getDestinationPort(),netInfo.getDestinationMac(),rtp.timestamp());
	}

	public AnalysisSIP(NetworkInfo networkInfo){
		//未初始化
          super.positiveNetworkInfo =networkInfo;
          super.reverseNetworkInfo=new NetworkInfo(networkInfo.getDestinationIP(), networkInfo.getSourceIP(), networkInfo.getDestinationMac(),networkInfo.getSourceMac(), networkInfo.getTransportLayer(), networkInfo.getDestinationPort(),networkInfo.getSourcePort());
	}
	
	
	public static AnalysisSIP getAnalysisSIP(NetworkInfo networkInfo){
		//   
		AnalysisSIP analysisSIP=null;
		analysisSIP=analysisSIPs.get(networkInfo.getNetworkInfoKey());
		if(analysisSIP!=null) {
			return analysisSIP;
		}
		analysisSIP=analysisSIPs.get(networkInfo.getReverseNetworkInfoKey());
		return analysisSIP;
	}
	
	
 
 
	 
	
	

	
	
	
 

	@Override
	public void initAnalysis() {
		super.sleepTime=CaptureNetPacketService.hertTimeOutPacket;
	}


	/**
	 * 被唤醒后，将数据包根据协议及时进行排序，避免网络抖动
	 */
	public void analysisSortPackageData(){

	}

	@Override
	public void analysisPackageData() {
		log.debug("start analysisPackageData SIP thread {} : sip包队列数量：{}",this.getPositiveNetworkInfo().getNetworkInfoKey(),sipPacketInfos.size());
		while(!sipPacketInfos.isEmpty()) {
			analysisSipPackageData(sipPacketInfos.poll());
		 
		}
		isTimeOut=Tools.isHeartTimeOutPacket(lastGetPacketDateTime);
			if(isTimeOut) {
				stopThread=true; 
				endAnalysis();
			}
		log.debug("处理后。analysisPackageData  SIP thread {} : sip包队列数量：{}",this.getPositiveNetworkInfo().getNetworkInfoKey(),sipPacketInfos.size());
	}
	public void analysisSipPackageData(SipPacketInfo sipPacketInfo) {
		try {
		/*	try {
				log.debug("analysisSipPackageData: {} 包体详细信息: {}", Tools.getjsonString(sipPacketInfo.getNetInfo()), sipPacketInfo.getSip());
			}catch (Exception e){
				log.error("analysisSipPackageData : {}",Tools.getjsonString( sipPacketInfo.getNetInfo()),e);
			}*/
	       if( positiveNetworkInfo.getNetworkInfoKey().equals(sipPacketInfo.getNetInfo().getNetworkInfoKey())){
	    	   //同一个方向的流
//	    	   analysisSIP.sips.put(Integer.parseInt(sip.fieldValue(Fields.CSeq)), sip);
	       }else{
	    	   //反方流
//	    	   analysisSIP.reverseSips.put(Integer.parseInt(sip.fieldValue(Fields.CSeq)), sip);
	       }
	       

	       currentSip=sipPacketInfo.getSip();
	       
//	       currentSdp=sipPacketInfo.getSdp();
		}catch (Exception e) {
		 log.error("analysisSipPackageData positiveNetworkInfo: {}",Tools.getjsonString(positiveNetworkInfo),e);
		}
		
		
		
		SignallingInfo currentSignallingInfo=null;
		try {
		String callid=null;
		callid=currentSip.fieldValue(Fields.Call_ID);
		if(callid==null)
			{
			log.debug(" callid is null {} ",sipPacketInfo.getNetInfo().getNetworkInfoKey());
			return ;
			}
		// 判断包的发送方向
		 boolean isClientToServer=false;
		 if(CaptureNetPacketService.getAppConfig().getSipServerIPs().contains(sipPacketInfo.getNetInfo().getDestinationIP())) {
			 // 客户端，发送给服务器的包
			 isClientToServer=true;
			 }
		 
		// 所有的信令
		currentSignallingInfo=callSignallingInfos.get(callid);
		if(currentSignallingInfo==null) 
		{
			 if(!currentSip.isResponse() && currentSip.fieldValue(Request.RequestMethod).equals(Method.INVITE.toString()))
			currentSignallingInfo= initSignallingInfo();
		}
		
		
		// 设置callid 唯一标识
		searchKeyAppData(CaptureNetPacketService.getAppConfig().getCallUUIDKey(),currentSignallingInfo);
		
		
		
		// **************************sip 头信息的处理
		 //返回消息的处理
	 if(currentSip.isResponse()) {
//		 1xx：临时消息：表示表示请求消息已经收到，后面将继续处理该请求。
//		 2xx：成功消息：表示请求已经被成功的理解、接受或执行。
//		 3xx：重定向消息：表示为了完成请求还需采取更进一步的动作。
//		 4xx：客户机错误：表示该请求含有语法错误或在这个服务器上不能被满足。
//		 5xx：服务器错误：表示该服务器不能处理一个明显有效的请求。
//		 6xx：全局性故障：表示该请求在任何服务器上都不能被实现。
		 
		 // 振铃，接通事件必须初始化过，没有初始化说明无效
		 if(currentSignallingInfo==null)return;
		 
		 if(isClientToServer) {
			 // 客户端，发送给服务器的包
			 if(currentSignallingInfo.getServerIP()==null) {
			 currentSignallingInfo.setClientIP(positiveNetworkInfo.getSourceIP());
	  		   currentSignallingInfo.setServerIP(positiveNetworkInfo.getDestinationIP());
			 	}
			 }else  {
			 //客户端接受，服务器的包
			 if(currentSignallingInfo.getServerIP()==null) {
			 currentSignallingInfo.setClientIP(positiveNetworkInfo.getDestinationIP());
  		   currentSignallingInfo.setServerIP(positiveNetworkInfo.getSourceIP());
			 }
		 }
		 
		 int responseCode=Integer.parseInt(currentSip.fieldValue(Response.ResponseCode));
		 // ring 状态180-199为振铃
	       if(responseCode>179 && responseCode<200) {
	    	   
	    	   if(isClientToServer) {
	    		   currentSignallingInfo.setDirection("in");
	    		   inboundRingEvent(currentSignallingInfo);
	    	   }else {
	    		   //客户端发给服务端的振铃消息时呼入
	    		   outboundRingEvent(currentSignallingInfo);
	    	   }
	    	   currentSignallingInfo.setRingTime(LocalDateTime.now());
	    	   // ring事件是一个状态sip，所以设置current
	    	    setRingingSip(currentSip);
	       }
	       //状态603表示电话忙被拒绝。需要释放掉
	       if(responseCode==603) {
	    	   if(currentSignallingInfo.getEndTime()==null) {
	  			   currentSignallingInfo.setEndTime(LocalDateTime.now());
	  			 setByeSip(currentSip);
	  			 releaseEvent(currentSignallingInfo);
	  			 stopThread=true;
	  		  } 
	    	  
	       }
			/*  判断简历连接的另一种方法
			 * else if(currentSip.fieldValue(Response.ResponseCode).equals("200")){ //
			 * 响应报文前一个有一个请求包的是建立连接的信号
			 * if(lastSip.getMessageType().equals(MessageType.REQUEST)) {
			 * if(lastSip.fieldValue(Request.RequestMethod).equals(Method.INVITE.toString())
			 * ) { //建立了连接成功。通话中.接通请求事件里有随路数据。
			 * if(currentSignallingInfo.getEstablishTime()==null) {
			 * currentSignallingInfo.setEstablishTime(LocalDateTime.now()); //
			 * 这是一个状态的sip，需要设置上一个的sip才是有效的建立连接的spi，上一个是一个发起请求的sip。
			 * currentSignallingInfo.setEstablishSip(lastSip);
			 * establishEvent(currentSignallingInfo); } }
			 * 
			 * } }
			 */
		 
		 
	 }else {
		 //请求消息的处理
//		 INVITE：用于发起呼叫请求。INVITE消息包括消息头和数据区两部分。INVITE 消息头包含主、被呼叫的地址，呼叫主题和呼叫优先级等信息。数据区则是关于会话媒体的信息，可由会话描述协议SDP 来实现。
//		 BYE：当一个用户决定中止会话时，可以使用BYE 来结束会话。
//		 OPTIONS：用于询问被叫端的能力信息，但OPTIONS 本身并不能发起呼叫。
//		 ACK：对已收到的消息进行确认应答。
//		 REGISTER：用于用户向SIP服务器传送位置信息或地址信息。
//		 CANCEL：取消当前的请求，但它并不能中止已经建立的连接。
		 if(currentSip.fieldValue(Request.RequestMethod).equals(Method.INVITE.toString())) {
			 
				//已经初始化。建立连接
				//如果前面是一个ACK确认的包，说明是接通信号。当前sip已经有UUID了。
			 if(lastSip!=null && !lastSip.isResponse()) {
				if(lastSip.fieldValue(Request.RequestMethod).equals(Method.ACK.toString())) {
					 //建立了连接成功。通话中.接通请求事件里有随路数据。
	 			   if(currentSignallingInfo.getEstablishTime()==null) {
	 				  currentSignallingInfo.setEstablishTime(LocalDateTime.now());
	 			   // 当前请求的sip即可分析出随路数据 
	 				 setEstablishSip(currentSip);
	 			   establishEvent(currentSignallingInfo);
	 			   } 
				}
			}
		 }else if(currentSip.fieldValue(Request.RequestMethod).equals(Method.BYE.toString())) {
			// 振铃，接通事件必须初始化过，没有初始化说明无效。结束通话
			 if(currentSignallingInfo==null)return;
			  // 挂断成功
			   if(currentSignallingInfo.getEndTime()==null) {
  			   currentSignallingInfo.setEndTime(LocalDateTime.now());
  			  setByeSip(currentSip);
  			 releaseEvent(currentSignallingInfo);
  			 stopThread=true;
  		  } 
		 }
	 }
		}catch (Exception e) {
			log.error("analysisSipPackageData Exception current {} \r\n last {}",currentSip,lastSip,e);
		}
		
		//    解析几个关键的随路数据信息，放到信令中
		try {
			analysisVoiceCallSignallingInfo(currentSignallingInfo);
		}catch (Exception e) {
			log.error("analysisVoiceCallSignallingInfo Exception current {} \r\n last {}",currentSip,lastSip,e);
		}
		
		//    sdp的解析，sdp信息在body体里面
		try {
			analysisSdpPackageData(currentSignallingInfo);
		}catch (Exception e) {
			log.error("analysisSDPPackageData Exception current {} \r\n last {}",currentSip,lastSip,e);
		}
	  lastSip=sipPacketInfo.getSip();
	}
	 // 解析每一个SDP获取创建的RTp端口。
	public void analysisSdpPackageData(SignallingInfo signallingInfo) {
		try {
			
		 if(signallingInfo==null)return;
		 Map<String,String> head=analysisSipHead(currentSip),body=null;
			
		 String mediaString=null;
		 String connectionInfoString=null;
		 String ownerString=null;
		 
		 if(currentSdp!=null) {
		 currentSdp.getAVP(Sdp.Fields.Media.toString());
		 currentSdp.getAVP(Sdp.Fields.ConnectionInfo.toString());
		 currentSdp.getAVP(Sdp.Fields.Owner.toString());
		 }
		 else if(head.get("Content-Type").equalsIgnoreCase("application/sdp"))
		 {
			 body=analysisSipPayload(currentSip);
			 head.putAll(body);
			 mediaString=head.get("m");
			 connectionInfoString=head.get("c");
			 ownerString=head.get("o");
			 log.debug("流媒体信息获取: {}",head);
		 }
		 String[] media =mediaString.split(" ");
		 String[] connectionInfo =connectionInfoString.split(" ");
		 String[] owner =ownerString.split(" ");
		 String sourcePort=null,sourceIP=null,sessionId=null,ownerIP=null;
		 // 获取rtp流的port
		 if(media.length>1)sourcePort=media[1];
		 if(connectionInfo.length>1)sourceIP=connectionInfo[2];
		 if(owner.length>1) {sessionId=owner[1];ownerIP=owner[5];}
		// 保存最后一次的信令，如果存在直接覆盖掉。 不用清理，占用的内存不多
		 clientSignallingCallInfos.put(sourceIP+">"+sourcePort, signallingInfo);
		 RedisConfig.setValue(sourceIP+">"+sourcePort,Tools.getjsonString(signallingInfo.toSignallingInfoDto()),1000*600);
		 log.debug("### analysisSdpPackageData ------>:{}, media info 解析出的流媒体信息: rtpIP:{},rtp Port:{},将RTP 的《ip>port》 作为redis key signallingInfo的信令信息存入redis缓存。sessionId:{},ownerIP:{}, signallingInfo: {}", positiveNetworkInfo.getNetworkInfoKey(),sourceIP,sourcePort,sessionId,ownerIP,Tools.getjsonString(signallingInfo));
		 }catch (Exception e) {
			 log.error("analysisSdpPackageData {} error:",currentSdp,e.getMessage());
		}
	}
	
	public SignallingInfo  initSignallingInfo() {
//		Sip.decodeFirstLine();对第一行解码，这个方法将第一行，根据是否SIP识别时状态行还是请求行。然后将对应数据设置进对象了。
//		   起始行分请求行（Request-Line）和状态行（Status-Line）两种。
//		  请求消息的起始行，由请求消息类型，请求目的发送地址Request-URI，SIP协议的版本号，之间用空格隔开。
//		   响应消息的起始行，SIP应答消息的Status-Line由SIP-Version开始，接着是一个数字编码的状态码Status-Code，最后是一个与状态码相关的描述性短语Reason-Phrase，然后由一个CRLF行结束符结束Status-Line。
		SignallingInfo signallingInfo=null;
		signallingInfo=callSignallingInfos.get(currentSip.fieldValue(Fields.Call_ID));
		if(signallingInfo==null) {
			signallingInfo=new SignallingInfo();
		signallingInfo.setCallId(currentSip.fieldValue(Fields.Call_ID));
		signallingInfo.setFromUser(currentSip.fieldValue(Fields.From));
		signallingInfo.setToUser(currentSip.fieldValue(Fields.To));
		 beginEvent(signallingInfo);
		 setBeginSip(currentSip);
		// 保存所有的信令
		callSignallingInfos.put(currentSip.fieldValue(Fields.Call_ID), signallingInfo);
		 
		log.debug(" ### AnalysisSIP initSignallingInfo :networkInfo key {},lastSignallingInfo: {}", positiveNetworkInfo.getNetworkInfoKey(),signallingInfo.toStringPart());
		signallingInfo.setCaller(Tools.getSipUserNumber(signallingInfo.getFromUser()));
		signallingInfo.setCalled(Tools.getSipUserNumber(signallingInfo.getToUser()));
		
		}else {

		}
		return signallingInfo;
	}
	
	
	
	
	
	
	
	/**
	 * 
		* <strong>Title: 快速设置callid等信息<strong>
		* <p>Description:获取随路数据 ,提供快速访问，提升性能其他数据后面解析.RTP流建立连接时解析.<p>
		* <p>Company: </p> 
		*<strong>Copyright:</strong> Copyright (c) 2019
		* @version: 1.0
		* @author  ASUS:augustWei
		* @date  2020 上午2:48:00
	 */
	public void searchKeyAppData(String key,SignallingInfo currentSignallingInfo) {
		if(currentSignallingInfo==null)return;
		if(key.trim().length()<1)
			{
			log.debug("未配置key，无需查calluuid");
			return  ;
			}
		Map appDataTemp;
		try {
			String text="";
			if(currentSignallingInfo.getCallUUID()==null && currentSip!= null) {
				 text=new String(currentSip.getHeader(),Charset.defaultCharset());
				 appDataTemp=changeLineToMap(text);
				 if(appDataTemp.get(key)!=null) currentSignallingInfo.setCallUUID(appDataTemp.get(key).toString());
			}
			 
		}catch (Exception e) {
			log.error("getCallidAppData:",e);
		}
	}
	
	
	/**
	 * 
		* <strong>Title: <strong>
		* <p>Description: rtp流结束时解析。 <p>
		* <p>Company: </p> 
		*<strong>Copyright:</strong> Copyright (c) 2019
		* @version: 1.0
		* @author  ASUS:augustWei
		* @date  2020 下午10:23:54
	 */
	public void analysisVoiceCallSignallingInfo(SignallingInfo currentSignallingInfo) {
		if(currentSignallingInfo==null)return;
		Map<String,String > appData;
		if(currentSignallingInfo.getAppData()==null)
			currentSignallingInfo.setAppData(new ConcurrentHashMap<String,String >());
		appData=currentSignallingInfo.getAppData();
		try {
			log.debug("### analysisVoiceCallSignallingInfo   getAppData begin >>>>>>>>>>");
			Map beginAppData, establishAppData,ringingAppData,byeAppData;
		// 解析开始的sip
		String text="";
		if(beginSip!=null && !beginSipAnalysis) {
			beginSipAnalysis=true;
		 text=new String(beginSip.getHeader(),Charset.defaultCharset());
		 log.debug("### analysisVoiceCallAppData getAppData \r\n beginSip: \r\n{}",text);
		 beginAppData=changeLineToMap(text);
		appData.putAll(beginAppData);
		}
		if(establishSip!=null  && !establishSipAnalysis) {
			establishSipAnalysis=true;
		// 建立连接的sip
		text=new String(establishSip.getHeader(),Charset.defaultCharset());
		log.debug("### analysisVoiceCallAppData getAppData \r\n establishSip:\r\n{}",text);
		establishAppData=changeLineToMap(text);
		appData.putAll(establishAppData);
		}
		if(ringingSip!=null&& !ringingSipAnalysis) {
			ringingSipAnalysis=true;
		// 解析振铃的sip
		text=new String(ringingSip.getHeader(),Charset.defaultCharset());
		log.debug("### analysisVoiceCallAppData getAppData \r\n ringingSip:\r\n {}",text);
		ringingAppData=changeLineToMap(text);
		appData.putAll(ringingAppData);
		}
		if(byeSip!=null && !byeSipAnalysis) {
			byeSipAnalysis=true;
		// 解析结束的sip
		text=new String(byeSip.getHeader(),Charset.defaultCharset());
			log.debug("### analysisVoiceCallAppData getAppData \r\n byeSip:\r\n {}",text);
		byeAppData=changeLineToMap(text);
		appData.putAll(byeAppData);
		// 特殊处理
		if(byeAppData.get("Reason")!=null) {
			currentSignallingInfo.setEndCase(byeAppData.get("Reason").toString());
			}
		}
	}catch (Exception e) {
		log.error("analysisVoiceCallSignallingInfo getAppData:",e);
	}
		}
	
	
	
	
	
	
	
	
	
	
	
	
	
		private void beginEvent(SignallingInfo signallingInfo) {
		 log.debug("beginEvent UUID:{} ,signallingInfo:{}",signallingInfo.getCallUUID(),signallingInfo.toStringPart());
		}
	 

		private void establishEvent(SignallingInfo signallingInfo) {
			 
			log.debug("establishEvent UUID:{} ,signallingInfo:{}",signallingInfo.getCallUUID(),signallingInfo.toStringPart());
	 
	}

		private void inboundRingEvent(SignallingInfo signallingInfo) {
			log.debug("inboundRingEvent UUID:{} ,signallingInfo:{}",signallingInfo.getCallUUID(),signallingInfo.toStringPart());
	 
	}

		private void outboundRingEvent(SignallingInfo signallingInfo) {
			log.debug("outboundRingEvent UUID:{} ,signallingInfo:{}",signallingInfo.getCallUUID(),signallingInfo.toStringPart());
	 
		}
		private void releaseEvent(SignallingInfo signallingInfo) {
			log.debug("releaseEvent UUID:{} ,signallingInfo:{}",signallingInfo.getCallUUID(),signallingInfo.toStringPart());
			 this.interrupt();
		}
 

	@Override
	public void handelAllPackageData() {
		
	}


	 
	
	
	
	@Override
	public void endAnalysis() {
		try {
			// 超时的时候处理的. 这个睡眠时间比RTp的睡眠时间长，保证了 信令能保留一段时间，不出现空指针的情况。信令在rtp结束时去解析和保存文件。
			// 这里保存会出问题，如果这个信令发起了会议，那么最后一次的信令保存的是前一次的，会出现一些问题，所以保存的工作放在了RTp里面去处理。也就是同一部话机进行两个外呼使用的是同一套端口号。
	     Thread.sleep(CaptureNetPacketService.hertTimeOutPacket);
		 //解析appdata。
		log.debug("flow endAnalysis ing signallingInfos : {}",positiveNetworkInfo.getNetworkInfoKey());
				
		 
		 
		
		
		} catch (InterruptedException e) {
		 log.debug("结束 。run {} 我被吵醒了，扔一块板砖出来提醒下吵醒我的人。 {}.", positiveNetworkInfo.getNetworkInfoKey(),e.getMessage());
					
	    }catch (Exception e) {
			log.error("endAnalysis:{}",positiveNetworkInfo.getNetworkInfoKey(),e);
		}finally {
			// 清理所有的sip
			analysisSIPs.remove(positiveNetworkInfo.getNetworkInfoKey());

		}
		log.debug("flow endAnalysis signallingInfos : {}  当前线程ID: {}",positiveNetworkInfo.getNetworkInfoKey(),Thread.currentThread().getId());
	}
	
	public Map<String,String> analysisSipHead(Sip sip) {
		String text=new String(sip.getHeader(),Charset.defaultCharset());
		Map<String,String > attr =changeLineToMap(text);
//		 log.debug("analysisSipHead  attr: \r\n{}",Tools.getjsonString(attr));
		 return attr;
	}
	public Map<String,String> analysisSipPayload(Sip sip) {
		String text=new String(sip.getPayload(),Charset.defaultCharset());
		Map<String,String > attr =changeLineToMap(text);
//		log.debug("analysisSipPayload  attr: \r\n{}",Tools.getjsonString(attr));
		return attr;
	}
	
	
	
	
	/**
	 * 
		* <strong>Title: sip的每一行转换后形成map<strong>
		* <p>Description: sip的每一行转换后形成map<p>
		* <p>Company: </p> 
		*<strong>Copyright:</strong> Copyright (c) 2019
		* @version: 1.0
		* @author  ASUS:augustWei
		* @date  2020 下午10:14:03
		* @param allLines
		* @return
	 */
	public Map changeLineToMap(String allLines) {
//		log.debug("---------------------------<<<<<<<<<<<<<<<<<<<<<\r\n{}",Tools.getjsonString(allLines));
		Map appData=null;
		try {
		  appData=new ConcurrentHashMap<String,String >();
		String[] allLine=allLines.split("\n");
		for (String line : allLine) {
			try {
				String[] attr=null;
				if(line.contains(":")) 
				{
				attr=line.split(":");
				}else if(line.contains("=")){
					attr=line.split("=");
				}
				
				if(attr!=null&&attr.length>1)
					appData.put(attr[0].trim(), attr[1].trim());
			} catch (Exception e) {
				log.error("changeLineToMap:{}",line,e);
			}
		}
		}catch (Exception e) {
			log.error("changeLineToMap:{}",e);
		}
		return appData;
	}

	public static void garbageCollection(){
		analysisSIPs.entrySet().forEach(analysisRTP->{
					analysisRTP.getValue().awaken();
				}
		);
	}

}
